<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- scope.qdoc -->
  <title>Scope and Naming Resolution | Qt QML 5.12.3</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td ><a href="../qtdoc/index.html">Qt 5.12</a></td><td ><a href="qtqml-index.html">Qt QML</a></td><td >
			范围和命名解析</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right"><a href="qtqml-index.html">Qt 5.12.3 参考指南</a></td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar">
<div class="toc">
<h3><a name="toc">目录</a></h3>
<ul>
<li class="level1"><a href="#javascript-scope">JavaScript范围</a></li>
<li class="level1"><a href="#type-names-and-imported-javascript-files">
类型名称和导入的JavaScript文件</a></li>
<li class="level1"><a href="#binding-scope-object">绑定对象范围</a></li>
<li class="level1"><a href="#component-scope">组件范围</a></li>
<li class="level1"><a href="#component-instance-hierarchy">组件实例层次结构</a></li>
<li class="level1"><a href="#overridden-properties">覆盖的属性</a></li>
<li class="level1"><a href="#javascript-global-object">JavaScript全局对象</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">范围和命名解析</h1>
<span class="subtitle"></span>
<!-- $$$qtqml-documents-scope.html-description -->
<div class="descr"> <a name="details"></a>
<p>
QML属性绑定、内联函数和导入的JavaScript文件都在JavaScript范围内运行。作用域控制表达式可以访问哪些变量，以及当两个或多个名称冲突时哪个变量优先。</p>
<p>由于JavaScript的内置作用域机制非常简单，QML对其进行了增强，使其更自然地适应QML语言扩展。</p>
<h2 id="javascript-scope">JavaScript范围</h2>
<p>
QML的作用域扩展不会干扰JavaScript的自然作用域。当在QML中编程函数、属性绑定或导入的JavaScript文件时，JavaScript程序员可以重用他们现有的知识。</p>
<p>在下面的示例中，<code>addConstant()</code>方法将向传入的参数添加13，正如程序员所期望的那样，而不考虑QML对象的<code>a</code>和<code>b</code>属性的值。</p>
<pre class="cpp">

  <span class="type"><a href="qml-qtqml-qtobject.html">QtObject</a></span> {
      property <span class="type">int</span> a: <span class="number">3</span>
      property <span class="type">int</span> b: <span class="number">9</span>

      function addConstant(b) {
          var a <span class="operator">=</span> <span class="number">13</span>;
          <span class="keyword">return</span> b <span class="operator">+</span> a;
      }
  }

</pre>
<p>QML尊重JavaScript的正常范围规则，甚至适用于绑定。这种完全邪恶、令人厌恶的绑定将为QML对象的属性赋值12。</p>
<pre class="cpp">

  <span class="type"><a href="qml-qtqml-qtobject.html">QtObject</a></span> {
      property <span class="type">int</span> a

      a: { var a <span class="operator">=</span> <span class="number">12</span>; a; }
  }

</pre>
<p>QML中的每个JavaScript表达式、函数或文件都有自己唯一的变量对象。在一个地方声明的局部变量永远不会与在另一个地方声明的局部变量发生冲突。</p>
<h2 id="type-names-and-imported-javascript-files">类型名称和导入的JavaScript文件</h2>
<p><a href="qtqml-documents-topic.html">QML文档</a>包括定义文档可见的类型名称和JavaScript文件的导入语句。除了在QML声明本身中使用类型名称外，JavaScript代码在访问<a href="qtqml-syntax-objectattributes.html#attached-properties-and-attached-signal-handlers">附加属性</a>和枚举值时也使用类型名称。</p>
<p>
导入的效果适用于QML文档中的每个属性绑定和JavaScript函数，甚至那些嵌套的内联组件。下面的示例显示了一个简单的QML文件，该文件访问一些枚举值并调用一个导入的JavaScript函数。</p>
<pre class="cpp">

  import <span class="type">QtQuick</span> <span class="number">2.0</span>
  import <span class="string">&quot;code.js&quot;</span> as Code

  ListView {
      snapMode: ListView<span class="operator">.</span>SnapToItem

      delegate: Component {
          Text {
              elide: Text<span class="operator">.</span>ElideMiddle
              text: <span class="string">&quot;A really, really long string that will require eliding.&quot;</span>
              color: Code<span class="operator">.</span>defaultColor()
          }
      }
  }

</pre>
<a name="binding-scope-object"></a>
<h2 id="binding-scope-object">绑定对象范围</h2>
<p>具有<a href="file:///E:/WLL/work/Qt5.12-Document-Trans-in-Chinese/qtqml/qtqml-syntax-propertybinding.html">属性绑定</a>的对象称为绑定的<i>作用域对象</i>。在以下示例中，<a href="file:///E:/WLL/work/Qt5.12-Document-Trans-in-Chinese/qtquick/qml-qtquick-item.html">Item</a>对象是绑定的作用域对象。</p>
<pre class="cpp">

  Item {
      anchors<span class="operator">.</span>left: parent<span class="operator">.</span>left
  }

</pre>
<p>绑定可以无限制地访问范围对象的属性。在前面的示例中，绑定直接访问<a href="file:///E:/WLL/work/Qt5.12-Document-Trans-in-Chinese/qtquick/qml-qtquick-item.html">Item</a>的<code>parent</code>属性，不需要任何形式的对象前缀。QML 为 JavaScript 引入了一种更加结构化、面向对象的方法，因此不需要使用 JavaScript 
的<code>this</code>属性。</p>
<p>由于它们与范围对象的交互，因此从绑定访问<a href="file:///E:/WLL/work/Qt5.12-Document-Trans-in-Chinese/qtqml/qtqml-syntax-objectattributes.html#attached-properties-and-attached-signal-handlers">附加属性</a>时必须小心。概念上附加的属性存在于<i>所有</i>对象上，即使它们只对<i>这些</i>对象的一个​​子集有影响。因此，未限定的附加属性读取将始终解析为作用域对象上的附加属性，这并不总是程序员所期望的。</p>
<p>例如，<a href="file:///E:/WLL/work/Qt5.12-Document-Trans-in-Chinese/qtquick/qml-qtquick-pathview.html">PathView</a>类型根据其在路径中的位置将内插值属性附加到其委托。由于<a href="file:///E:/WLL/work/Qt5.12-Document-Trans-in-Chinese/qtquick/qml-qtquick-pathview.html">PathView</a>仅有意义地将这些属性附加到委托中的根对象，因此任何访问它们的子对象都必须明确限定根对象，如下所示。</p>
<pre class="cpp">

  PathView {
      delegate: Component {
          Rectangle {
              id: root
              Image {
                  scale: root<span class="operator">.</span>PathView<span class="operator">.</span>scale
              }
          }
      }
  }

</pre>
<p>如果<a href="file:///E:/WLL/work/Qt5.12-Document-Trans-in-Chinese/qtquick/qml-qtquick-image.html">Image</a>对象省略了<code>root</code>前缀，它会无意中访问<code>PathView.scale</code>自身未设置的附加属性。</p>
<a name="component-scope"></a>
<h2 id="component-scope">组件范围</h2>
<p>QML 文档中的每个 QML 组件都定义了一个逻辑范围。每个文档至少有一个根组件，但也可以有其他内联子组件。组件范围是组件内的对象 ID 和组件的根对象属性的联合。</p>
<pre class="cpp">

  Item {
      property string title

      Text {
          id: titletype
          text: <span class="string">&quot;&lt;b&gt;&quot;</span> <span class="operator">+</span> title <span class="operator">+</span> <span class="string">&quot;&lt;/b&gt;&quot;</span>
          font<span class="operator">.</span>pixelSize: <span class="number">22</span>
          anchors<span class="operator">.</span>top: parent<span class="operator">.</span>top
      }

      Text {
          text: titletype<span class="operator">.</span>text
          font<span class="operator">.</span>pixelSize: <span class="number">18</span>
          anchors<span class="operator">.</span>bottom: parent<span class="operator">.</span>bottom
      }
  }

</pre>
<p>上面的示例显示了一个简单的 QML 组件，它在顶部显示富文本标题字符串，在底部显示相同文本的较小副本。第一种<code>Text</code>类型<code>title</code>在形成要显示的文本时直接访问组件的属性。根类型的属性可以直接访问，这使得在整个组件中分发数据变得微不足道。</p>
<p>第二种<code>Text</code>类型使用 id 直接访问第一种的文本。ID 由 QML 程序员明确指定，因此它们始终优先于其他属性名称（<a href="file:///E:/WLL/work/Qt5.12-Document-Trans-in-Chinese/qtqml/qtqml-documents-scope.html#javascript-scope">JavaScript Scope </a>
<span lang="zh-cn">中</span><span lang="zh-cn">的</span>那些除外）。例如，万一绑定的<a href="file:///E:/WLL/work/Qt5.12-Document-Trans-in-Chinese/qtqml/qtqml-documents-scope.html#binding-scope-object">范围对象</a><code>titletype</code>在前面的示例中具有属性，则<code>titletype</code>id 仍将优先。</p>
<a name="component-instance-hierarchy"></a>
<h2 id="component-instance-hierarchy">组件实例层次结构</h2>
<p>在 QML 中，组件实例将它们的组件范围连接在一起以形成范围层次结构。组件实例可以直接访问其祖先的组件范围。</p>
<p>证明这一点的最简单方法是使用内联子组件，其组件范围被隐式限定为外部组件的子组件。</p>
<pre class="cpp">

  Item {
      property color defaultColor: <span class="string">&quot;blue&quot;</span>

      ListView {
          delegate: Component {
              Rectangle {
                  color: defaultColor
              }
          }
      }
  }

</pre>
<p>组件实例层次结构允许委托组件的实例访问<code>Item</code> 类型的<code>defaultColor</code> 
属性。当然，如果委托组件有一个名为<code>defaultColor</code> 的属性，它就会优先。</p>
<p>.组件实例范围层次结构也扩展到线外组件。在下面的例子中，TitlePage。qml组件创建两个<code>TitleText</code> 
实例。即使TitleText类型在一个单独的文件中，当从<code>TitlePage</code>中使用它时，它仍然可以访问<code>title</code> 
属性。QML是一种动态作用域语言——根据使用它的位置，<code>title</code> 属性可能有不同的解析。</p>
<pre class="cpp">

  <span class="comment">// TitlePage.qml</span>
  import <span class="type">QtQuick</span> <span class="number">2.0</span>
  Item {
      property string title

      TitleText {
          size: <span class="number">22</span>
          anchors<span class="operator">.</span>top: parent<span class="operator">.</span>top
      }

      TitleText {
          size: <span class="number">18</span>
          anchors<span class="operator">.</span>bottom: parent<span class="operator">.</span>bottom
      }
  }

  <span class="comment">// TitleText.qml</span>
  import <span class="type">QtQuick</span> <span class="number">2.0</span>
  Text {
      property <span class="type">int</span> size
      text: <span class="string">&quot;&lt;b&gt;&quot;</span> <span class="operator">+</span> title <span class="operator">+</span> <span class="string">&quot;&lt;/b&gt;&quot;</span>
      font<span class="operator">.</span>pixelSize: size
  }

</pre>
<p>动态范围非常强大，但必须谨慎使用，以防止 QML 代码的行为变得难以预测。一般来说，它应该只在两个组件已经以另一种方式紧密耦合的情况下使用。在构建可重用组件时，最好使用属性接口，如下所示：</p>
<pre class="cpp">

  <span class="comment">// TitlePage.qml</span>
  import <span class="type">QtQuick</span> <span class="number">2.0</span>
  Item {
      id: root
      property string title

      TitleText {
          title: root<span class="operator">.</span>title
          size: <span class="number">22</span>
          anchors<span class="operator">.</span>top: parent<span class="operator">.</span>top
      }

      TitleText {
          title: root<span class="operator">.</span>title
          size: <span class="number">18</span>
          anchors<span class="operator">.</span>bottom: parent<span class="operator">.</span>bottom
      }
  }

  <span class="comment">// TitleText.qml</span>
  import <span class="type">QtQuick</span> <span class="number">2.0</span>
  Text {
      property string title
      property <span class="type">int</span> size

      text: <span class="string">&quot;&lt;b&gt;&quot;</span> <span class="operator">+</span> title <span class="operator">+</span> <span class="string">&quot;&lt;/b&gt;&quot;</span>
      font<span class="operator">.</span>pixelSize: size
  }

</pre>
<h2 id="overridden-properties">覆盖的属性</h2>
<p>QML 允许在对象声明中定义的属性名称被另一个对象声明中声明的属性覆盖，该属性扩展了第一个。例如：</p>
<pre class="cpp">

  <span class="comment">// Displayable.qml</span>
  import <span class="type">QtQuick</span> <span class="number">2.0</span>
  Item {
      property string title
      property string detail

      Text {
          text: <span class="string">&quot;&lt;b&gt;&quot;</span> <span class="operator">+</span> title <span class="operator">+</span> <span class="string">&quot;&lt;/b&gt;&lt;br&gt;&quot;</span> <span class="operator">+</span> detail
      }

      function getTitle() { <span class="keyword">return</span> title }
      function setTitle(newTitle) { title <span class="operator">=</span> newTitle }
  }

  <span class="comment">// Person.qml</span>
  import <span class="type">QtQuick</span> <span class="number">2.0</span>
  Displayable {
      property string title
      property string firstName
      property string lastName

      function fullName()  { <span class="keyword">return</span> title <span class="operator">+</span> <span class="string">&quot; &quot;</span> <span class="operator">+</span> firstName <span class="operator">+</span> <span class="string">&quot; &quot;</span> <span class="operator">+</span> lastName }
  }

</pre>
<p>在这里，名称<code>title</code> 既用于Displayable的输出文本的标题，也用于Person对象的尊称标题。</p>
<p>覆盖的属性根据引用它的范围进行解析。在 Person 组件的作用域内，或从引用 Person 组件实例的外部作用域，<code>title</code>解析为在 Person.qml 中声明的属性。该<code>fullName</code>函数将引用<code>title</code>在 Person 中声明的属性。</p>
<p>但是，在 Displayable 组件内部，<code>title</code>指的是 Displayable.qml 中声明的属性。getTitle() 和 setTitle() 函数以及<code>text</code>Text 对象属性的绑定都将引用<code>title</code>Displayable 组件中声明的属性。</p>
<p>尽管名称相同，但这两个属性是完全独立的。其中一个属性的 onChanged 信号处理程序不会因更改另一个同名属性而触发。任一属性的别名将引用一个或另一个，但不能同时引用两者。</p>
<a name="javascript-global-object"></a>
<h2 id="javascript-global-object">JavaScript全局对象</h2>
<p>QML 不允许与全局对象上的属性冲突的类型、id 和属性名称以防止任何混淆。程序员可以确信<code>Math.min(10, 9)</code>会始终按预期工作！</p>
<p>有关更多信息，请参阅<a href="file:///E:/WLL/work/Qt5.12-Document-Trans-in-Chinese/qtqml/qtqml-javascript-hostenvironment.html">JavaScript 主机环境</a>。</p>
</div>
<!-- @@@qtqml-documents-scope.html -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2019 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br/>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br/>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>
